﻿#include "knumber.h"
#include <ctype.h>
#include <cstring>

namespace ikit{
  static char time_str[256];

// MurmurHash2 64-bit variant
static uint64_t MurmurHash64B(const void* key, int len, unsigned int seed) {
  const unsigned int m = 0x5bd1e995;
  const int r = 24;
  unsigned int h1 = seed ^ len;
  unsigned int h2 = 0;
  const unsigned int* data = (const unsigned int*)key;

  while (len >= 8) {
    unsigned int k1 = *data++;
    k1 *= m;
    k1 ^= k1 >> r;
    k1 *= m;
    h1 *= m;
    h1 ^= k1;
    len -= 4;
    unsigned int k2 = *data++;
    k2 *= m;
    k2 ^= k2 >> r;
    k2 *= m;
    h2 *= m;
    h2 ^= k2;
    len -= 4;
  }

  if (len >= 4) {
    unsigned int k1 = *data++;
    k1 *= m;
    k1 ^= k1 >> r;
    k1 *= m;
    h1 *= m;
    h1 ^= k1;
    len -= 4;
  }

  switch (len) {
  case 3:
    h2 ^= ((unsigned char*)data)[2] << 16;
  case 2:
    h2 ^= ((unsigned char*)data)[1] << 8;
  case 1:
    h2 ^= ((unsigned char*)data)[0];
    h2 *= m;
  };

  h1 ^= h2 >> 18;
  h1 *= m;
  h2 ^= h1 >> 22;
  h2 *= m;
  h1 ^= h2 >> 17;
  h1 *= m;
  h2 ^= h1 >> 19;
  h2 *= m;

  uint64_t h = h1;
  h = (h << 32) | h2;
  return h;
}

// MurmurHash1 32-bit variant
static uint32_t murmurhash1_32(const void* key, size_t len, uint32_t seed) {
  const uint8_t* data = (const uint8_t*)key;
  uint32_t h = seed;

  while (len >= 4) {
    uint32_t k = *(uint32_t*)data;
    k *= 0xcc9e2d51;
    k = (k << 15) | (k >> 17);
    k *= 0x1b873593;

    h ^= k;
    h = (h << 13) | (h >> 19);
    h *= 5;

    data += 4;
    len -= 4;
  }

  // Handle remaining bytes (if any)
  uint32_t k = 0;
  switch (len) {
  case 3:
    k ^= data[2] << 16;
  case 2:
    k ^= data[1] << 8;
  case 1:
    k ^= data[0];
    k *= 0xcc9e2d51;
    k = (k << 15) | (k >> 17);
    k *= 0x1b873593;
    h ^= k;
  }

  // Finalize the hash value
  h ^= len;
  h ^= h >> 16;
  h *= 0x85ebca6b;
  h ^= h >> 13;
  h *= 0xc2b2ae35;
  h ^= h >> 16;

  return h;
}

uint32_t hash(const char* str) {
  if (str == nullptr) {
    return -1;
  }
  return murmurhash1_32(str, static_cast<int>(strlen(str)), 0x12345678);
}

uint64_t hash64(const char* str) {
  if (str == nullptr) {
    return -1;
  }
  return MurmurHash64B(str, static_cast<int>(strlen(str)), 0x12345678);
}




bool is_number(const char* s) {
  if (s == NULL) {
    return false;
  }
  int count = 0; // 这个用来记录第一个
  // 这个s[i]真太妙了。原来还能这样！
  for (int i = 0; s[i]; i++) {
    if (s[i] < '0' || s[i] > '9') {
      // 第一位可以是负号
      if (s[i] == '-' && count == 0) {
        continue;
      }
      // 忽略空格
      if (s[i] == ' ') {
        continue;
      }

      return false;
    }

    // 如果是因为空格跳过，这里不会增加。所以，前面可以有空格。
    count++;
    if (count > 32) {
      return false;
    }
  }

  return true;
}

bool is_float(const char* s) {
  if (s == NULL) {
    return false;
  }

  int count = 0; // 这个用来记录第一个
  int floatCount = 0;

  // 这个s[i]真太妙了。原来还能这样！
  for (int i = 0; s[i]; i++) {
    if (s[i] < '0' || s[i] > '9') {
      // 可以是点号，但只能是一个
      if (s[i] == '.') {
        if (floatCount == 0) {
          floatCount++;
          continue;
        } else {
          return false;
        }
      }

      // 第一位可以是负号
      if (s[i] == '-' && count == 0) {
        continue;
      }
      // 忽略空格
      if (s[i] == ' ') {
        continue;
      }

      return false;
    }

    // 如果是因为空格跳过，这里不会增加。所以，前面可以有空格。
    count++;
    if (count > 32) {
      return false;
    }
  }

  return true;
}

bool is_hex(const char* s) {
  if (s == NULL) {
    return false;
  }
  int lower;

  // 这个s[i]真太妙了。原来还能这样！
  for (int i = 0; s[i]; i++) {
    lower = tolower(s[i]);

    bool isNumber = lower >= '0' && lower <= '9';
    bool isHex = lower >= 'a' && lower <= 'f';

    if (!(isNumber || isHex)) {
      return false;
    }
  }

  return true;
}

int hex_to_number(char ch) {
  if (ch >= '0' && ch <= '9') {
    return ch - '0';
  }
  if (ch >= 'A' && ch <= 'Z') {
    return ch - 'A' + 10;
  }
  if (ch >= 'a' && ch <= 'z') {
    return ch - 'a' + 10;
  }
  return 0;
}

// 输入字符串，输出相应的16进制；例如：输入"12AB3d"，输出0x12AB3d
uint32_t hex_to_uint(const char* buf) {
  uint32_t sum = 0;
  uint32_t num = 0;
  char ch = 0;

  for (int i = 0; buf[i]; i++) {
    ch = buf[i];

    // 如果前面有0x，需要跳过
    if (ch == '0' && i == 0) {
      continue;
    }
    if (ch == 'x' && i == 1) {
      continue;
    }

    if (ch >= '0' && ch <= '9') {
      num = ch - '0';
    }

    if (ch >= 'A' && ch <= 'F') {
      num = ch - 'A' + 10;
    }

    if (ch >= 'a' && ch <= 'f') {
      num = ch - 'a' + 10;
    }

    sum = sum * 16 + num; // 16进制表达
  }
  return sum;
}

}